/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.github.florent37.camerafragment.configuration;

import ohos.media.camera.params.ParameterKey;
import ohos.utils.Parcel;
import ohos.utils.Sequenceable;

import com.github.florent37.camerafragment.internal.utils.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.CLASS;
import static java.lang.annotation.RetentionPolicy.SOURCE;

/**
 * 自定义注解
 *
 * @since 2021-05-21
 */
public final class Configuration implements Sequenceable {
    /**
     * TAG
     */
    public static final String TAG = "Configuration";
    /**
     * 默认
     */
    public static final int MEDIA_QUALITY_AUTO = 10;
    /**
     * 画面质量最高
     */
    public static final int MEDIA_QUALITY_LOWEST = 15;
    /**
     * 画面质量最低
     */
    public static final int MEDIA_QUALITY_LOW = 11;
    /**
     * 画面质量中等
     */
    public static final int MEDIA_QUALITY_MEDIUM = 12;
    /**
     * 画面质量高
     */
    public static final int MEDIA_QUALITY_HIGH = 13;
    /**
     * 画面质量较高
     */
    public static final int MEDIA_QUALITY_HIGHEST = 14;
    /**
     * 录像
     */
    public static final int MEDIA_ACTION_VIDEO = 100;
    /**
     * 拍照
     */
    public static final int MEDIA_ACTION_PHOTO = 101;
    /**
     * 位置
     */
    public static final int MEDIA_ACTION_UNSPECIFIED = 102;
    /**
     * 前置
     */
    public static final int CAMERA_FACE_FRONT = 0x6;
    /**
     * 后置
     */
    public static final int CAMERA_FACE_REAR = 0x7;
    /**
     * 向上
     */
    public static final int SENSOR_POSITION_UP = 90;
    /**
     * 倒着108
     */
    public static final int SENSOR_POSITION_UP_SIDE_DOWN = 270;
    /**
     * 向左
     */
    public static final int SENSOR_POSITION_LEFT = 0;
    /**
     * 向右
     */
    public static final int SENSOR_POSITION_RIGHT = 180;
    /**
     * 未知转向
     */
    public static final int SENSOR_POSITION_UNSPECIFIED = -1;
    /**
     * 页面旋转0°
     */
    public static final int DISPLAY_ROTATION_0 = 0;
    /**
     * 页面旋转90°
     */
    public static final int DISPLAY_ROTATION_90 = 90;
    /**
     * 页面旋转180°
     */
    public static final int DISPLAY_ROTATION_180 = 180;
    /**
     * 页面旋转270°
     */
    public static final int DISPLAY_ROTATION_270 = 270;
    /**
     * 竖屏
     */
    public static final int ORIENTATION_PORTRAIT = 0x111;
    /**
     * 横屏
     */
    public static final int ORIENTATION_LANDSCAPE = 0x222;
    /**
     * 闪光灯开
     */
    public static final int FLASH_MODE_ON = 1;
    /**
     * 闪光灯关
     */
    public static final int FLASH_MODE_OFF = 2;
    /**
     * 闪光灯自动
     */
    public static final int FLASH_MODE_AUTO = 3;
    /**
     * 设置Parameter Key
     */
    public static final ParameterKey.Key<Integer> CONTROL_AF_TRIGGER =
        new ParameterKey.Key<>("hos.control.afTrigger", int.class);

    /**
     * 设置Parameter Key
     */
    public static final ParameterKey.Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
        new ParameterKey.Key<>("hos.control.aePrecaptureTrigger", int.class);

    /**
     * 设置Parameter Key
     */
    public static final ParameterKey.Key<Integer> CONTROL_AE_MODE =
        new ParameterKey.Key<>("hos.control.aeMode", int.class);

    /**
     * 设置Parameter Key
     */
    public static final ParameterKey.Key<Integer> FLASH_MODE =
        new ParameterKey.Key<>("hos.flash.mode", int.class);

    private static final int DEFAULT = -1;
    @MediaAction
    private int mediaAction = DEFAULT;

    @MediaQuality
    private int mediaQuality = DEFAULT;

    @CameraFace
    private int cameraFace = DEFAULT;

    private int videoDuration = DEFAULT;

    private long videoFileSize = DEFAULT;

    private int minimumVideoDuration = DEFAULT;

    @FlashMode
    private int flashMode = FLASH_MODE_AUTO;

    @Override
    public boolean marshalling(Parcel parcel) {
        return false;
    }

    @Override
    public boolean unmarshalling(Parcel parcel) {
        return false;
    }

    /**
     * 注解 媒体画面质量
     *
     * @since 2021-05-24
     */
    @IntDef({MEDIA_QUALITY_AUTO, MEDIA_QUALITY_LOWEST, MEDIA_QUALITY_LOW,
        MEDIA_QUALITY_MEDIUM, MEDIA_QUALITY_HIGH, MEDIA_QUALITY_HIGHEST})
    @Retention(RetentionPolicy.SOURCE)
    public @interface MediaQuality {
    }

    /**
     * 注解 媒体动作
     *
     * @since 2021-05-24
     */
    @IntDef({MEDIA_ACTION_VIDEO, MEDIA_ACTION_PHOTO, MEDIA_ACTION_UNSPECIFIED})
    @Retention(RetentionPolicy.SOURCE)
    public @interface MediaAction {
    }

    /**
     * 注解 闪光灯模式
     *
     * @since 2021-05-24
     */
    @IntDef({FLASH_MODE_ON, FLASH_MODE_OFF, FLASH_MODE_AUTO})
    @Retention(RetentionPolicy.SOURCE)
    public @interface FlashMode {
    }

    /**
     * 注解 前后置摄像头
     *
     * @since 2021-05-24
     */
    @IntDef({CAMERA_FACE_FRONT, CAMERA_FACE_REAR})
    @Retention(RetentionPolicy.SOURCE)
    public @interface CameraFace {
    }

    /**
     * 注解 传感器方向
     *
     * @since 2021-05-24
     */
    @IntDef({SENSOR_POSITION_UP, SENSOR_POSITION_UP_SIDE_DOWN, SENSOR_POSITION_LEFT,
        SENSOR_POSITION_RIGHT, SENSOR_POSITION_UNSPECIFIED})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SensorPosition {
    }

    /**
     * 注解 页面旋转角度
     *
     * @since 2021-05-24
     */
    @IntDef({DISPLAY_ROTATION_0, DISPLAY_ROTATION_90, DISPLAY_ROTATION_180, DISPLAY_ROTATION_270})
    @Retention(RetentionPolicy.SOURCE)
    public @interface DisplayRotation {
    }

    /**
     * 旋转方向
     *
     * @since 2021-05-24
     */
    @IntDef({ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface DeviceDefaultOrientation {
    }

    /**
     * 创建Builder
     *
     * @since 2021-05-24
     */
    public static class Builder {
        private Configuration configuration;

        /**
         * 构造方法
         */
        public Builder() {
            configuration = new Configuration();
        }

        /**
         * 设置媒体动作
         *
         * @param mediaAction 媒体操作
         * @return Builder 创建者
         */
        public Builder setMediaAction(@MediaAction int mediaAction) {
            configuration.mediaAction = mediaAction;
            return this;
        }

        /**
         * 设置媒体画面质量
         *
         * @param mediaQuality 画质
         * @return Builder 创建者
         */
        public Builder setMediaQuality(@MediaQuality int mediaQuality) {
            configuration.mediaQuality = mediaQuality;
            return this;
        }

        /**
         * 设置录像时间
         *
         * @param videoDuration 录像时间
         * @return Builder 创建者
         */
        public Builder setVideoDuration(@IntRange(from = 1000, to = Integer.MAX_VALUE) int videoDuration) {
            configuration.videoDuration = videoDuration;
            return this;
        }

        /**
         * 设置最小录像时间
         *
         * @param minimumVideoDurationInMilliseconds 最小录像时间
         * @return Builder 创建者
         */
        public Builder setMinimumVideoDuration(@IntRange(from = 1000, to = Integer.MAX_VALUE)
                                                   int minimumVideoDurationInMilliseconds) {
            configuration.minimumVideoDuration = minimumVideoDurationInMilliseconds;
            return this;
        }

        /**
         * 设置录像文件大小
         *
         * @param videoSizeInBytes 文件大小
         * @return Builder 创建者
         */
        public Builder setVideoFileSize(@IntRange(from = 1048576, to = Long.MAX_VALUE)
                                            long videoSizeInBytes) {
            configuration.videoFileSize = videoSizeInBytes;
            return this;
        }

        /**
         * 设置闪光灯模式
         *
         * @param flashMode 闪光灯模式
         * @return Builder 创建者
         */
        public Builder setFlashMode(@FlashMode int flashMode) {
            configuration.flashMode = flashMode;
            return this;
        }

        /**
         * 设置相机
         *
         * @param camera 相机
         * @return Builder 创建者
         */
        public Builder setCamera(@CameraFace int camera) {
            configuration.cameraFace = camera;
            return this;
        }

        /**
         * build创建
         *
         * @return Configuration 配置项
         * @throws IllegalArgumentException 参数异常
         */
        public Configuration build() {
            try {
                if (configuration.mediaQuality == MEDIA_QUALITY_AUTO && configuration.minimumVideoDuration < 0) {
                    configuration = new Configuration();
                }
            } catch (IllegalStateException e) {
                Log.error(TAG, "Please provide minimum video duration in milliseconds to use auto quality.");
            }
            return configuration;
        }
    }

    @MediaAction
    public int getMediaAction() {
        return mediaAction;
    }

    public int getMediaQuality() {
        return mediaQuality;
    }

    @CameraFace
    public int getCameraFace() {
        return cameraFace;
    }

    public int getVideoDuration() {
        return videoDuration;
    }

    public long getVideoFileSize() {
        return videoFileSize;
    }

    public int getMinimumVideoDuration() {
        return minimumVideoDuration;
    }

    @FlashMode
    public int getFlashMode() {
        return flashMode;
    }

    /**
     * 没有注解自己定义
     *
     * @since 2021-05-24
     */
    @Retention(SOURCE)
    @Target({ANNOTATION_TYPE})
    public @interface IntDef {
        /**
         * 为该元素定义允许的常量
         *
         * @return long[]数组
         */
        long[] value() default {};

        /**
         * 定义常量是否可以用作标志，或仅作为枚举(默认)
         *
         * @return boolean是否用作标志
         */
        boolean flag() default false;
    }

    /**
     * 没有注解自己定义
     *
     * @since 2021-05-24
     */
    @Retention(CLASS)
    @Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE})
    public @interface IntRange {
        /**
         * 最小值
         *
         * @return long类型
         */
        long from() default Long.MIN_VALUE;

        /**
         * 最大的价值
         *
         * @return long类型
         */
        long to() default Long.MAX_VALUE;
    }

    /**
     * 目标API
     *
     * @since 2021-05-24
     */
    @Target({TYPE, METHOD, CONSTRUCTOR})
    @Retention(CLASS)
    public @interface TargetApi {
        /**
         * 这为类型设置了目标api级别
         *
         * @return int整数
         */
        int value();
    }

    /**
     * 元素类型
     *
     * @since 2021-05-24
     */
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(CLASS)
    public @interface SuppressLint {
        /**
         * 应该是的一组警告(由lint问题id标识)
         * 被lint忽略。指定无法识别的名称不是错误。
         *
         * @return String[]数组
         */
        String[] value();
    }

    /**
     * 自定义权限注解
     *
     * @since 2021-05-24
     */
    @Retention(CLASS)
    @Target({ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER})
    public @interface RequiresPermission {
        /**
         * 如果只需要一个权限，则需要的权限名称。如果需要多个权限，则指定{@link #allOf()}或{@link #anyOf()}。
         * 如果指定，{@link #anyOf()}和{@link #allOf()}必须都为空。
         *
         * @return String字符串
         */
        String value() default "";

        /**
         * 指定所有必需的权限名列表。
         * 如果指定，{@link #anyOf()}和{@link #value()}必须都为空。
         *
         * @return String[]数据
         */
        String[] allOf() default {};

        /**
         * 如果指定，{@link #allOf()}和{@link #value()}必须同时为空。
         *
         * @return String[]数组
         */
        String[] anyOf() default {};

        /**
         * 如果为true，则不一定在所有情况下都需要该许可(例如，它可能只在某些平台或某些调用参数等上强制执行)。
         *
         * @return boolean类型
         */
        boolean conditional() default false;

        /**
         * 指定读取操作需要给定的权限。当在参数上指定时，注释指出该方法需要一个权限，
         * 该权限取决于参数的值(通常传入的对应字段将是一组常量中的一个，
         * 这些常量已经被注释了{@code @RequiresPermission})。
         *
         * @since 2021-05-24
         */
        @Target({FIELD, METHOD, PARAMETER})
        @interface Read {
            RequiresPermission value() default @RequiresPermission;
        }

        /**
         * 指定写操作需要给定的权限。当在参数上指定时，注释指出该方法需要一个权限，
         * 该权限取决于参数的值(通常传入的对应字段将是一组常量中的一个，
         * 这些常量已经被注释了{@code @RequiresPermission})。
         *
         * @since 2021-05-24
         */
        @Target({FIELD, METHOD, PARAMETER})
        @interface Write {
            RequiresPermission value() default @RequiresPermission;
        }
    }
}
